# -*- coding: utf-8 -*-
# __author__: yb
# Version 1.0
# Contact: yb890102@126.com

from ctypes import *
from pkt_build import *
import time, binascii
import ConfigParser
from winpcapy import *

def winp_send_packet(sendBuff, netCard):
    fp=pcap_t
    errbuf= create_string_buffer(PCAP_ERRBUF_SIZE)
    packet=(c_ubyte * len(sendBuff))()
    ## Open the adapter
    fp = pcap_open_live(netCard, 65536, 1, 1000, errbuf)
    if not bool(fp):
        print "Unable to open the adapter.\n[%s] is not supported by WinPcap\n"%netCard
        return -1
    for i in range(0, len(sendBuff)):
        packet[i] = struct.unpack('B', sendBuff[i])[0]
    ## Send down the packet
    if (pcap_sendpacket(fp, packet, len(sendBuff)) != 0):
        print "\nError sending the packet: %s\n" % pcap_geterr(fp)
        return -2
    pcap_close(fp)

def readconfig():
    import ConfigParser
    cf = ConfigParser.ConfigParser()
    cf.read('config.ini')
    res_dic = {}
    try:
        res_dic['netcard'] = cf.get('basic_conf', 'netcard')
        res_dic['send_count'] = cf.getint('basic_conf', 'send_count')
        res_dic['send_interval'] = cf.getfloat('basic_conf', 'send_interval')
        res_dic['eth_src'] = cf.get('eth_header', 'src_mac')
        res_dic['eth_dst'] = cf.get('eth_header', 'dst_mac')
        res_dic['sip'] = cf.get('ip_header', 'src')
        res_dic['dip'] = cf.get('ip_header', 'dst')
        res_dic['ttl'] = cf.getint('ip_header', 'ttl')
        if res_dic['ttl'] <0 or res_dic['ttl']>128:
            print 'error ttl'
            return
        try:
            res_dic['protocol'] = cf.getint('ip_header', 'protocol')
        except:
            if cf.get('ip_header', 'protocol').lower() == 'tcp':
                res_dic['protocol'] = 6
            elif cf.get('ip_header', 'protocol').lower() == 'udp':
                res_dic['protocol'] = 17
            else:
                print 'error ip_header  protocol'
                return
        res_dic['sport'] = cf.getint('udp_header', 'sport')
        res_dic['dport'] = cf.getint('udp_header', 'dport')
        #tcp
        res_dic['tcp_sport'] = cf.getint('tcp_header', 'sport')
        res_dic['tcp_dport'] = cf.getint('tcp_header', 'dport')
        try:
            f = cf.getint('tcp_header', 'flags')
            if f >= 0 and f < 128:
                res_dic['tcp_flags'] = f
            else:
                print 'error tcp flags!'
                return
        except:
            flags_map = {'syn': 2, 'ack': 16, 'push': 8}
            if cf.get('tcp_header', 'flags') in flags_map.keys():
                res_dic['tcp_flags'] = flags_map[cf.get('tcp_header', 'flags')]
            else:
                print 'error tcp flags!'
                return
        res_dic['tcp_options'] = cf.get('tcp_header', 'options')
        res_dic['data_type'] = cf.get('data', 'data_type')
        if res_dic['data_type'].lower() == 'hex':
            res_dic['data'] = binascii.a2b_hex(cf.get('data', 'data'))
        else:
            res_dic['data'] = cf.get('data', 'data')
    except Exception, e:
        print 'config error!', e
        return
    return res_dic

def main():
    conf = readconfig()
    netcard = conf['netcard']
    if conf['protocol'] == 17:
        sport, dport = conf['sport'], conf['dport']
        pkt = buildPacket(conf['eth_src'], conf['eth_dst'], conf['sip'],
                          conf['dip'], conf['protocol'], sport, dport)
    elif conf['protocol'] == 6:
        sport, dport = conf['tcp_sport'], conf['tcp_dport']
        pkt = buildPacket(conf['eth_src'], conf['eth_dst'], conf['sip'],
                          conf['dip'], conf['protocol'], sport, dport)
        pkt.set_tcp_flags(conf['tcp_flags'])
        if conf['tcp_options']:
            pkt.add_tcp_options(conf['tcp_options'])
    pkt.add_payload(conf['data'])
    sendbuff = pkt.pack()
    print repr(sendbuff)
    for i in xrange(conf['send_count']):
        try:
            winp_send_packet(sendbuff, netcard)
            print '. ',
        except Exception, e:
            print 'send packet error: %s\n%s'%(repr(sendbuff), e)
            return
        if conf['send_interval']:
            time.sleep(conf['send_interval'])

def test():
    a = '\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x01\x08\x00\x45'
    netcard = '\Device\NPF_{0B2B85FF-C568-4AEE-B064-75EA29DBD423}'
    winp_send_packet(a, netcard)

if __name__ == '__main__':
    #test()
    main()